﻿/**
 * Classe représentant chaque lien envoyé à la Freebox
 */
var FreeboxLink = function(url)
{
	// L'URL du lien
	var _url;
	// Si le fichier est un .torrent
	var _isTorrent;
	// Le message de chargement en cours
	var _messageLoading = null
	
	var _this = this;
	
	/**
	 * Renvoie l'URL du lien
	 *
	 * @return {String} L'URL du lien
	 */
	this.getURL = function()
	{
		return _url;
	};
	
	/**
	 * Envoie l'ajout du lien dans la liste de téléchargement de la Freebox
	 */
	this.addFileToFreebox = function()
	{
		// Si c'est un torrent, appel de la fonction en relation
		if (_isTorrent)
			_addTorrent();
		// Sinon, celle du fichier normal
		else
			_addFile();
		
		// Affichage du message de chargement en cours
		_messageLoading = new Message("loadingLink.html?link="+encodeURIComponent(_url),0,{html: true});
		_messageLoading.show();
	};
	
	/**
   * Récupère l'URL de la Freebox avec un chemin ajouté
   *
   * @param {String} parturl la partie d'URL a ajouté au chemin
   */
  function _getURL(parturl)
  {
    var accesDistant = Storage.get("acces-distant-freebox") || false;
    var baseurl = "";
    if (accesDistant == "1")
    {
		var ip = Storage.get("acces-distant-freebox-ip");
		var port = Storage.get("acces-distant-freebox-port");
		baseurl = "http://"+ip;
		
		if (port != "80") {
			baseurl += ":"+port;
		}
    }
    else
		baseurl = FreeboxLink.BASE_URL_LOCAL;
	
	if (parturl != undefined) {
		baseurl += parturl;
	}
    return baseurl;
  }

	/**
	 * Fonction permettant d'envoyer un lien non-torrent à la Freebox
	 */
	function _addFile()
	{
		FreeboxLink.puts("addFile "+_url);
		
		// Les paramètres du formulaire
		var params = {
			"csrf_token": FreeboxLink.token,
			"url": encodeURIComponent(_url),
			"user": "freebox",
			"method": "download.http_add",
		};

		// Envoie de la requête POST
		var req = new Request(_getURL(FreeboxLink.BASE_FORM), Request.POST, params);
		req.onload = _onAddResponse;
		req.onerror = _onError;
		req.start();
	}
	
	/**
	 * Fonction permettant d'envoyer un lien torrent à la Freebox
	 */	
	function _addTorrent()
	{
		FreeboxLink.puts("addTorrent "+_url);
		
		// Les paramètres du formulaire
		var params = {
			"csrf_token": FreeboxLink.token,
			"url": encodeURIComponent(_url),
			"user": "freebox",
			"method": "download.torrent_add"
		}

		// Envoie de la requête POST
		var req = new Request(_getURL(FreeboxLink.BASE_FORM), Request.POST, params);
		req.onload = _onAddResponse;
		req.onerror = _onError
		req.start();
	}

	function _onError(e,req)
	{
		// Récupération du status
		var status = req.getStatus();

		if (e == null || status == 0)
    {
      _messageLoading.close();
      if (_getURL() == FreeboxLink.BASE_URL_LOCAL)
        var mes = "Impossible de contacter la Freebox. Etes-vous sûr d'être abonné chez Free avec une Freebox v6?"
      else
        var mes = "Impossible de contacter la Freebox. Etes-vous sûr que l'adresse externe de la Freebox est: "+_getURL()+" ?";
      var m = new Message(mes,10000);
			m.show();
    }
	}
	/**
	 * Ecouteur déclenché lorsque la réponse a été envoyé par la Freebox
	 *
	 * @param {Event} e l'évènement XmlHttpRequest
	 * @param {Request} req l'objet Request associé
	 */
	function _onAddResponse(e,req)
	{
		// Récupération du status
		var status = req.getStatus();
		
		// Si c'est un status "forbidden", il faut s'identifier
		
		if (status == 403)
		{
			console.log("Identification nécessaire...");
			_loginWithStorage();
			_messageLoading.close();
			return;
		}
		
		// On parse le JSON renvoyé par la Freebox
		try {
			var obj = JSON.parse(req.getResponseText());
		} catch(e) {
			console.log("Le format renvoyé n'est pas du JSON.");
		}
		// On supprime le message de chargement
		_messageLoading.close();
		
		// Si l'ajout a été effectué, le paramètre "result" est envoyé
		if (obj.result)
		{
			// Message de confirmation
			var mes = new Message('Le lien suivant a été ajouté dans la liste des téléchargements: \n'+_url,3000, { title: 'Lien ajouté !'} );
			mes.show();
		}
		else
		{
			// Si l'ajout n'a pas été effectué, un paramètre "errcode" est envoyé
			switch(obj.errcode)
			{
				// 11: le lien existe déjà?
				case 11:
					var text = "Le lien existe déjà dans la liste des téléchargements !";
					break;
				default:
					var text = 'Le lien suivant n\'a pas pu être ajouté dans la liste des téléchargements (errcode: '+obj.errcode+'): \n'+_url;
					break;
			}
			// Affichage du message
			var mes = new Message(text,3000, { title: 'Erreur !'} );
			mes.show();
		}
	}
	
	/**
	 * Envoie la requête d'identification avec un mot de passe précis
	 *
	 * @param {String} pwd le mot de passe à utilisé
	 */
	this.loginWithPassword = function(pwd)
	{
		_login(pwd);
	};
	
	/**
	 * Envoie la requête d'identification avec un mot de passe
	 *
	 * @param {String} pwd le mot de passe à utilisé
	 */
	function _login(password)
	{
		// Paramètres du formulaire d'identification à la Freebox
		var params = {
			"login": "freebox",
			"passwd": password
		};
		
		// Envoie de la requête
		var req = new Request(_getURL(FreeboxLink.FORM_LOGIN), Request.POST, params);
		req.onload = _onLogin;
		req.start();
	};
	
	/**
	 * Envoie la requête d'identification avec le mot de passe stocké
	 *
	 * S'il n'y en a pas, une popup pour s'identifier s'affiche.
	 */
	function _loginWithStorage()
	{
		console.log("Login sur mafreebox...");
		var password = Storage.get("password-freebox");
		
		// Si aucun mot de passe a été stocké, on affiche un formulaire d'identification
		if (!password || password == "")
		{
			// On supprime le message de chargement
			_messageLoading.close();
			// On affiche celui pour s'identifier
			FreeboxLink.lastLink = _this;
			FreeboxLink.showLoginMessage();
			return;
		}
		
		// Sinon, envoie de la requête avec le mot de passe
		_login(password)
		
	}
	

	
	/**
	 * Ecouteur déclenché lorsque la réponse de la requête d'identification a été reçue
	 *
	 * @param {Event} e l'évènement XmlHttpRequest
	 * @param {Request} req l'objet Request associé
	 */
	function _onLogin(e,req)
	{
		var status = req.getStatus();
		
		// Si le status vaut 200
		if (status == 200)
		{
			var obj = JSON.parse(req.getResponseText());
			// Si le paramètre result est envoyé et vaut true, alors l'identification a été effectué
			if (obj.result) {
				_getInfos(); // On récupère d'abord la version et le token
				//_this.addFileToFreebox();
			}
			// Sinon, le mot de passe est incorrect
			else
			{
				// Affichage du message du mot de passe incorrect
				var mes = new Message('Impossible de se connecter à la Freebox !\nLe mot de passe est erronée.', 3000, { title: 'Erreur !'} );
				mes.show();
			}
		}
		else
		{
			// Si ce n'est pas 200, total inconnu !
			console.log(req.getResponseText());
			console.log(req.getStatus());
		}
	};
	
	/**
	 * Lance la requête d'obtention des informations
	 */
	function _getInfos() {
		var req = new Request(_getURL(FreeboxLink.PAGE_DOWNLOAD), Request.GET);
		req.onload = _onGetInfos;
		req.onerror = _onError;
		req.start();
	};

	/**
	 * Obtient des informations
	 */
	function _onGetInfos(e,req) {
		var status = req.getStatus();
		
		if (status == 200)
		{
			var html = req.getResponseText();
			
			// Récupère la version dans la page d'info système
			// Commenté car non utile: Si on trouve le token, on le met, sinon non
			/*
			var htmlpartinfo = html.substring(html.indexOf('<div id="col_1"'));
			var regexp = /<li>Version[^<>]*<span>([^<>]*)<\/span><\/li>/gim;
			var result = regexp.exec(htmlpartinfo);
			
			_version = 0;
			if (result) {
				var regexp_version_num = new RegExp("[0-9.]*");
				
				if (regexp_version_num.test(result[1])) {
					_version = parseInt(result[1].replace(/\./g,""));
					if (_version < 1000) { // 1.1.2 => 1.1.2.0
						_version *= 10;
					}
					if (_version < 100) { // 1.2 => 1.2.0.0
						_version *= 100;
					}
				}
			}
			*/
			

			var regexp = /input type="hidden" name="csrf_token" value="([^"]*)"/gi;
			var result = regexp.exec(html);
			if (result) {
				FreeboxLink.token = encodeURIComponent(result[1]);
			}
			
			Request.html = html;
			_this.addFileToFreebox();
		} else {
		}
	}
	/**
	 * Constructeur de la classe
	 *
	 * Initialise les différents attributs, et identifie les liens torrents des liens non-torrents
	 *
	 * @param {String} url L'URL du lien
	 */
	function _construct(url)
	{
		_url = url;
		
		// Si c'est un lien magnet = torrent
		var isMagnet = (url.beginsWith("magnet:"));
		// Si c'est dans les exceptions = torrent
		var isException = TorrentExceptions.test(url);
		
		noparamurl = url;
		
		// URL sans les paramètres
		if (!isException && !isMagnet && url.indexOf("?") != -1)
			noparamurl = url.substr(0,url.indexOf("?"));
		
		// C'est un torrent si cela finit par .torrent, ou que c'est dans les exceptions ou si c'est un lien magnet
		var isTorrent = (isException || isMagnet || noparamurl.endsWith(".torrent"));
		
		_isTorrent = isTorrent;		
	};
	
	// Appel du constucteur
	_construct(url);
	
};

// URL de base pour une freebox locale
FreeboxLink.BASE_URL_LOCAL = "http://mafreebox.freebox.fr"
// URL pour l'ajout de téléchargement
FreeboxLink.BASE_FORM = "/download.cgi"
// URL pour l'identification
FreeboxLink.FORM_LOGIN = "/login.php"
// URL pour récupérer un token hidden
FreeboxLink.PAGE_DOWNLOAD = "/download.php";
// URL pour récupérer la version de la Freebox
FreeboxLink.PAGE_INFO_SYSTEME = "/settings.php?page=misc_system";

// Token général à toute les requêtes
FreeboxLink.token = undefined;

/**
 * Ecouteur déclenché lors du clic sur l'élément du menu contextuel
 */
FreeboxLink.onclickURL = function(e)
{
	// Récupération de l'URL
	var link = (typeof(e.linkUrl) != "undefined")? e.linkUrl : e.srcUrl;
	url = link.toString();

	// Création d'un nouveau lien
	var freeboxLink = new FreeboxLink(link);
	freeboxLink.addFileToFreebox();	
};

/**
 * Initialisation de la classe: ajoute l'écouteur sur le clic du menu contextuel
 */
FreeboxLink.init = function()
{
	ContextMenu.onclick = FreeboxLink.onclickURL
};

/**
 * Affiche un message formatté à la console
 *
 * @param {Object} o L'objet à afficher
 */
FreeboxLink.puts = function(o)
{
	if (typeof(o) == "string")
		console.log("{FreeboxLink - FreeboxLink} "+o);
	else
		console.log(o);
};

/**
 * Permet de lancer l'identification sur une URL avec un password
 *
 * @param {String} url l'url du lien lorsque l'identification était nécessaire
 * @param {String} password le mot de passe à utiliser
 */
FreeboxLink.loginWithPassword = function(url,password)
{
	var link = new FreeboxLink(url);
	link.loginWithPassword(password);
};

/**
 * Affiche le formulaire d'identification
 */
FreeboxLink.showLoginMessage = function()
{
	// S'il n'existe pas encore, on le crée
	if (!FreeboxLink.loginMessage)
		FreeboxLink.loginMessage = new Message('loginFreebox.html?link='+encodeURIComponent(FreeboxLink.lastLink.getURL()), 0, { html: true });
	
	// Puis on l'affiche
	FreeboxLink.loginMessage.show();
};

/**
 * Cache le formulaire d'identification
 */
FreeboxLink.hideLoginMessage = function()
{
	FreeboxLink.loginMessage.close();
};
